package com.starsoft.smdc.crawler.common;

import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.starsoft.frame.base.service.FlexsetService;
import com.starsoft.smdc.crawler.sina.SinaService;
import com.starsoft.smdc.dao.MarketDailyDao;
import com.starsoft.smdc.dao.SmdcSecurityDao;
import com.starsoft.smdc.service.HolidayService;

public abstract class CrawlerService {
	
	private static Logger logger = LoggerFactory.getLogger(SinaService.class);

	protected final String SMDC_EXCHANGE = "SMDC_EXCHANGE";
	protected final String SMDC_FUND_CLASS="SMDC_FUND_CLASS";
	protected final String SMDC_SECURITY_TYPE="SMDC_SECURITY_TYPE";
	
	@Autowired
	protected FlexsetService flexsetService;
	@Autowired
	protected SmdcSecurityDao securityDao;
	@Autowired
	protected MarketDailyDao marketDailyDao;
	@Autowired
	protected HolidayService holidayService;
	
	protected String url;
	protected Map<String, String> apiMap;

	protected HttpClient httpClient;
	
	
	public String request(String apiName, String... params) {
		String requestUrl = getRequestUrl(apiName, params);
		String result = null;
		try {
			logger.info("Request Url: " + requestUrl);
			HttpGet httpGet = new HttpGet(requestUrl);
			httpGet.setHeaders(defaultHeaders(requestUrl));
			HttpResponse httpresponse = getHttpClient().execute(httpGet);
			result = EntityUtils.toString(httpresponse.getEntity());
			result = result.trim();
		} catch (Exception e) {
			logger.error(apiName, e);
		}
		return result;
	}

	public InputStream downLoad(String apiName, String... params) {
		String requestUrl =  getRequestUrl(apiName, params);
		InputStream is = null;
		try {
			logger.info("Download Url: " + requestUrl);
			HttpGet httpGet = new HttpGet(requestUrl);
			httpGet.setHeaders(defaultHeaders(requestUrl));
			HttpEntity entity = getHttpClient().execute(httpGet).getEntity();
			is = entity.getContent();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return is;
	}
	
	protected synchronized HttpClient getHttpClient() {
		try {
			if (httpClient == null) {
				httpClient = HttpClients.createDefault();
			}
			return httpClient;
		} catch (Exception e) {
			throw new RuntimeException("Crawler Get HttpClient Failed", e);
		}
	}
	
	protected HttpClient getTrustedHttpsClient() {
		X509TrustManager x509mgr = new X509TrustManager() {
			public void checkClientTrusted(X509Certificate[] xcs, String string) {
			}

			public void checkServerTrusted(X509Certificate[] xcs, String string) {
			}

			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};
		SSLConnectionSocketFactory sslsf = null;
		try {
			SSLContext sslContext = SSLContext.getInstance("TLS");
			sslContext.init(null, new TrustManager[] { x509mgr }, null);
			sslsf = new SSLConnectionSocketFactory(sslContext);
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		RequestConfig config = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
		return HttpClients.custom().setDefaultRequestConfig(config).setSSLSocketFactory(sslsf).build();
	}

	
	protected abstract String getTargetSystem();

	protected abstract String convertSecId(String secId, boolean isToLocal);
	
	protected Header[] defaultHeaders(String url) {
		return null;
	}

	protected String convertExchange(String exchange, boolean isToLocal) {
		String newExchange = null;
		if (isToLocal) {
			newExchange = flexsetService.codeConvertFrom(SMDC_EXCHANGE, exchange, getTargetSystem());
		} else {
			newExchange = flexsetService.codeConvertTo(SMDC_EXCHANGE, exchange, getTargetSystem());
		}
		return newExchange;
	}
	
	protected String convertExchange(Map<String, Object> mapObject){
		String exchange = convertExchange((String)mapObject.get("exchange"), true);
		mapObject.put("exchange", exchange);
		return exchange;
	}
	
	protected String convertSecType(String secTye, boolean isToLocal) {
		String newExchange = null;
		if (isToLocal) {
			newExchange = flexsetService.codeConvertFrom(SMDC_SECURITY_TYPE, secTye, getTargetSystem());
		} else {
			newExchange = flexsetService.codeConvertTo(SMDC_SECURITY_TYPE, secTye, getTargetSystem());
		}
		return newExchange;
	}
	
	protected String convertSecType(Map<String, Object> mapObject){
		String secType = convertSecType((String)mapObject.get("secType"), true);
		mapObject.put("secType", secType);
		return secType;
	}
	
	private String getRequestUrl(String apiName, String... params) {
		String requestUrl = url;
		if(url == null){
			requestUrl = "";
		}
		if(!apiMap.containsKey(apiName)){
			throw new RuntimeException(String.format("没有API:%s,%s", this.getTargetSystem(), apiName));
		}
		requestUrl += apiMap.get(apiName);
		requestUrl = String.format(requestUrl, (Object[]) params);
		return requestUrl.trim();
	}
	
	public JsonNode getJsonNode(String str) {
		try {
			ObjectMapper obMapper = new ObjectMapper();
			JsonNode root = obMapper.readTree(str);
			return root;
		} catch (Exception e) {
			throw new RuntimeException("解析json失败", e);
		}
	}

	
	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public Map<String, String> getApiMap() {
		return apiMap;
	}

	public void setApiMap(Map<String, String> apiMap) {
		this.apiMap = apiMap;
	}
	

}
